package com.gonsin.gview.common.controller;


import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.gonsin.base.ResponseResult;
import com.gonsin.base.exceptions.MyException;
import com.gonsin.gview.common.auth.BaseResultCodes;
import com.gonsin.gview.common.auth.WebApi;
import com.gonsin.gview.common.po.FileUploadBo;
import com.gonsin.gview.common.services.IUpdateService;
import com.gonsin.gview.common.utils.PathUtils;
import com.gonsin.gview.logic.config.GViewFileProperties;
import com.gonsin.gview.common.utils.ImageUtils;
import com.gonsin.gview.common.utils.MD5Util;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;

@Slf4j
@Api(tags = "上传接口")
@RestController
@RequestMapping("/api/base")
public class UploadController {

    @Autowired
    private IUpdateService updateService;
    @Autowired
    private GViewFileProperties config;


    // TODO 提防文件无限制上传
//    @ApiOperationSupport(order = 3001)
//    @ApiOperation("上传 - 准备文件上传（弃用）")
//    @Deprecated
//    @RequestMapping(value = "/upload/files/ready", method = RequestMethod.POST)
//    public String readyToUpdate(){
//        return updateService.readyToUpdate(url);
//    }


    @ApiOperationSupport(order = 3002)
    @ApiOperation("上传 - 准备文件上传")
    @WebApi(login = true)
    @RequestMapping(value = "/upload/files/ready/request", method = RequestMethod.POST)
    public ResponseResult<String> readyToUpdateRequest(@ApiParam("原始路径(可选)") @RequestParam(value = "url", required = false) String url,
                                                       @ApiParam("文件后缀") @RequestParam(value = "suffix", required = false) String suffix) {
        return ResponseResult.result(updateService.readyToUpdate(url, suffix));
    }


    @ApiOperationSupport(order = 3003)
    @ApiOperation("上传 - 上传文件(分片上传)")
    @WebApi(login = true)
    @RequestMapping(value = "/upload/files", method = RequestMethod.POST)
    public ResponseResult<Void> updateFilePieces(
            @ApiParam("上传秘钥") @RequestParam(name = "key") String key,
            @ApiParam("分片的文件") @RequestParam(name = "piece") MultipartFile piece,
            @ApiParam("第几个分片，从0开始") @RequestParam(name = "index") int index,
            @ApiParam("是否最后一个分片") @RequestParam(name = "end", required = false, defaultValue = "false") boolean end) throws IOException {
        updateService.update(key, piece, index, end);
        return ResponseResult.simpleResult();
    }

    @ApiOperationSupport(order = 3004)
    @ApiOperation("上传 - 获取文件url和md5")
    @WebApi(login = true)
    @GetMapping("/upload/files/url")
    public ResponseResult<FileUploadBo> getUrl(@ApiParam("上传秘钥") @RequestParam(name = "key") String key) {
        return ResponseResult.result(updateService.getUrlByKey(key));
    }

    /**
     * 上传文件
     */
    // TODO 需要防止重复上传，大数据量上传等等
    @ApiOperationSupport(order = 3005)
    @ApiOperation(value = "上传 - 上传文件", consumes = "如果是图片，会额外生成720p的图片地址")
    @ResponseBody
    @WebApi(login = true)
    @PostMapping(value = "/upload")
    public ResponseResult<FileUploadBo> handleUpload(
            @ApiParam("文件") @RequestParam("file") MultipartFile file,
            @ApiParam("原始路径(可选)") @RequestParam(value = "url", required = false) String url
    ) throws IOException {

        String md5;
        // 检查是否上传了文件
        if (file.isEmpty()) {
            throw new MyException(BaseResultCodes.PARAM_ERROR, "上传文件为空");
        }

        // 检查文件大小
        String mid = RandomStringUtils.random(32, true, true);
        // 用户上传的文件存储到的文件夹的名称
        File dest = null;
        String suffixName = FilenameUtils.getExtension(file.getOriginalFilename());
        if (url == null
                || url.equalsIgnoreCase("null")
                || url.equals("")
                || url.equalsIgnoreCase("undefined")) {
            String uploadDirName = "/temp";
            String parentDirPath = config.getTempPath() + File.separator;
            File parentDir = new File(parentDirPath);
            if (!parentDir.exists()) {
                parentDir.mkdirs();
            }
            String fileName = mid + "." + suffixName;
            url = uploadDirName + "/" + fileName;
            dest = new File(parentDir, fileName);
        } else {
            dest = new File(PathUtils.getPathFromUrl(config.getTempPath(), url));
        }
        if (dest.exists()) {
            dest.delete();
        }
        if(!dest.getParentFile().exists()){
            dest.getParentFile().mkdirs();
        }
        dest.createNewFile();
        file.transferTo(dest);
        md5 = MD5Util.getMd5ByFile(dest);

        FileUploadBo bo = new FileUploadBo();
        if (isImageFile(FilenameUtils.getExtension(file.getOriginalFilename()))) {
            File dest720p = new File(dest.getAbsolutePath() + ".720p." + suffixName);
            ImageUtils.ImageSize size = ImageUtils.getImgWidth(dest);
            float scale = 720f / (float) Math.min(size.height, size.width);
            ImageUtils.reduceImg(dest, dest720p, 0, 0, scale);
            bo.setUrl720p(url + ".720p." + suffixName);
            bo.setWidth(size.width);
            bo.setHeight(size.height);
        }

        bo.setMd5(md5);
        bo.setUrl(url);
        return ResponseResult.result(bo);
    }


    private static boolean isImageFile(String ext) {
        if (ext == null) {
            return false;
        }
        ext = ext.toLowerCase();
        if (ext.equals("jpg")) {
            return true;
        }
        if (ext.equals("png")) {
            return true;
        }
        if (ext.equals("jpeg")) {
            return true;
        }
        if (ext.equals("bmp")) {
            return true;
        }
        if (ext.equals("gif")) {
            return true;
        }
        return false;
    }
}

